package com.jeomo.mem.starter.service.impl;

import com.jeomo.base.starter.service.impl.BaseServiceImpl;
import com.jeomo.common.core.exception.BusinessException;
import com.jeomo.common.util.DoubleUtil;
import com.jeomo.masterdata.starter.entity.Level;
import com.jeomo.masterdata.starter.mapper.LevelMapper;
import com.jeomo.mem.starter.entity.MemberLevelDailyExe;
import com.jeomo.mem.starter.entity.MemberLevelExe;
import com.jeomo.mem.starter.entity.MemberLevelExeUpdate;
import com.jeomo.mem.starter.enums.MemLevelSrcTypeEnum;
import com.jeomo.mem.starter.mapper.MemberCardMapper;
import com.jeomo.mem.starter.mapper.MemberLevelDailyExeMapper;
import com.jeomo.mem.starter.mapper.MemberLevelExeMapper;
import com.jeomo.shiro.util.OrgUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;

/**
 * 会员等级执行单服务
 * @author:Jackpot
 * @create 2021-01-14 11:35
 * @description:
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class MemberLevelExeService extends BaseServiceImpl<MemberLevelDailyExeMapper, MemberLevelDailyExe> {

    @Resource
    private MemberLevelExeMapper memberLevelExeMapper;
    @Resource
    private MemberLevelDailyExeMapper memberLevelDailyExeMapper;
    @Resource
    private LevelMapper levelMapper;
    @Resource
    private MemberCardMapper memberCardMapper;

    /**
     * 更新会员等级执行信息(统一调用该接口)
     * @param memberLevelExeUpdate
     */
    public void updateLevelExe(MemberLevelExeUpdate memberLevelExeUpdate){

        String cardNo = memberLevelExeUpdate.getCardNo();
        String levelCode = memberLevelExeUpdate.getLevelCode();
        LocalDateTime handleTime = memberLevelExeUpdate.getHandleTime();
        Double acquireAmount = memberLevelExeUpdate.getAcquireAmount();
        Integer acquirePoints = memberLevelExeUpdate.getAcquirePoints();
        acquireAmount = acquireAmount!=null?acquireAmount:0D;
        acquirePoints = acquirePoints!=null?acquirePoints:0;
        Level level = levelMapper.selectById(levelCode);
        recursiveCal(cardNo,handleTime,level,acquireAmount,acquirePoints);
    }

    public void recursiveCal(String cardNo,LocalDateTime handleTime,Level level,double acquireAmount,int acquirePoints){

        String levelCode = level.getCode();
        LocalDate thatDate = handleTime.toLocalDate();
        Integer effectiveDay = level.getEffectiveDay();
        Integer upLevelSumBonus = level.getUpLevelSumBonus();//升级累计积分
        Double upLevelSumAmount = level.getUpLevelSumAmount();//升级累计金额
        Double upLevelDailyAmount = level.getUpLevelDailyAmount();//升级累计单日金额
        MemberLevelExe memberLevelExe = memberLevelExeMapper.queryLevelExe(cardNo, levelCode,handleTime);
        if (memberLevelExe==null){//会员注册时就已经初始化等级执行信息
            int srcType = MemLevelSrcTypeEnum.UP.getCode();
            memberLevelExe = initLevelExe(cardNo,levelCode,handleTime,handleTime.plusDays(effectiveDay).toLocalDate(),srcType);
        }
        if (acquireAmount<=0D && acquirePoints<=0) return;
        if (acquireAmount<0D) acquireAmount=0D;
        if (acquirePoints<0) acquirePoints=0;

        int curTotalPoints = memberLevelExe.getTotalPoints() + acquirePoints;
        double curTotalAmount = DoubleUtil.add(memberLevelExe.getTotalAmount(), acquireAmount);
        MemberLevelDailyExe memberLevelDailyExe = memberLevelDailyExeMapper.queryLevelDailyExec(cardNo, levelCode, thatDate);
        double dailyAmount = memberLevelDailyExe!=null?memberLevelDailyExe.getTotalAmount():0;
        double dailyTotalAmount = DoubleUtil.add(dailyAmount, acquireAmount);
        if (curTotalPoints>=upLevelSumBonus || curTotalAmount>=upLevelSumAmount || dailyTotalAmount >=upLevelDailyAmount){//升级
            Level nextLevel = levelMapper.getNextLevel(level.getOrgCode(), level.getLevelCode());
            if (nextLevel!=null){ //情况1:升级会员卡
                int i = memberCardMapper.updateCardLevel(cardNo, nextLevel.getCode());
                if (i!=1) throw new BusinessException("会员卡升级失败!");
            }else{//情况2:已经最高等级,无法升级
                accAdd(memberLevelExe,acquirePoints,acquireAmount,thatDate);
                return;
            }
            int points = Math.min(curTotalPoints, upLevelSumBonus) - memberLevelExe.getTotalPoints();
            double amount = DoubleUtil.sub(Math.min(curTotalAmount, upLevelSumAmount), memberLevelExe.getTotalAmount());
            accAdd(memberLevelExe,points,amount,thatDate);
            //更新会员等级执行信息状态为已评定
            memberLevelExe.setRating(true);
            int i = memberLevelExeMapper.updateById(memberLevelExe);
            if (i!=1) throw new BusinessException("更新会员等级执行信息失败!");
            //将下一等级的执行信息初始化,递归检查是否满足再次升级
            acquireAmount = DoubleUtil.sub(curTotalAmount,upLevelSumAmount);
            acquirePoints = curTotalPoints - upLevelSumBonus;
            recursiveCal(cardNo,handleTime,nextLevel,acquireAmount,acquirePoints);
        }else{ //情况3:不满足升级条件,累加
            accAdd(memberLevelExe,acquirePoints,acquireAmount,thatDate);
        }
    }

    /**
     * 初始化会员等级执行单
     */
    public MemberLevelExe initLevelExe(String cardNo,String levelCode,LocalDateTime startTime,LocalDate endTime,int srcType){

        MemberLevelExe memberLevelExe = new MemberLevelExe();
        memberLevelExe.setCardNo(cardNo);
        memberLevelExe.setLevelCode(levelCode);
        memberLevelExe.setStartTime(startTime);
        memberLevelExe.setEndTime(endTime);//到期时间
        memberLevelExe.setTotalPoints(0);
        memberLevelExe.setTotalAmount(0D);
        memberLevelExe.setSrcType(srcType);
        int insert = memberLevelExeMapper.insert(memberLevelExe);
        if (insert!=1)  throw new BusinessException("初始化会员等级执行单失败!");
        return memberLevelExe;
    }

    /**
     * 累加
     * @param memberLevelExe
     */
    public void accAdd(MemberLevelExe memberLevelExe,int acquirePoints,double acquireAmount,LocalDate thatDate){
        memberLevelExe.setTotalPoints(memberLevelExe.getTotalPoints()+acquirePoints);
        memberLevelExe.setTotalAmount(DoubleUtil.add(memberLevelExe.getTotalAmount(), acquireAmount));
        int i = memberLevelExeMapper.updateById(memberLevelExe);
        if (i!=1)  throw new BusinessException("更新会员等级执行单明细失败!");

        MemberLevelDailyExe memberLevelDailyExe = memberLevelDailyExeMapper.queryLevelDailyExe(memberLevelExe.getId(), thatDate);
        if (memberLevelDailyExe==null){
            memberLevelDailyExe = new MemberLevelDailyExe();
            memberLevelDailyExe.setPid(memberLevelExe.getId());
            memberLevelDailyExe.setCardNo(memberLevelExe.getCardNo());
            memberLevelDailyExe.setLevelCode(memberLevelExe.getLevelCode());
            memberLevelDailyExe.setThatDay(thatDate);
            memberLevelDailyExe.setTotalPoints(acquirePoints);
            memberLevelDailyExe.setTotalAmount(acquireAmount);
            int insert = memberLevelDailyExeMapper.insert(memberLevelDailyExe);
            if (insert!=1)  throw new BusinessException("初始化会员等级执行单明细失败!");
        }else{
            memberLevelDailyExe.setTotalPoints(memberLevelDailyExe.getTotalPoints()+acquirePoints);
            memberLevelDailyExe.setTotalAmount(DoubleUtil.add(memberLevelDailyExe.getTotalAmount(), acquireAmount));
            int j = memberLevelDailyExeMapper.updateById(memberLevelDailyExe);
            if (j!=1)  throw new BusinessException("更新会员等级执行单明细失败!");
        }
    }


}
